home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / LAPB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-14  |  21.8 KB  |  840 lines

  1. /* Link Access Procedures Balanced (LAPB), the upper sublayer of
  2.  * AX.25 Level 2.
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  * 92/02/07 WG7J
  6.  * Modified to drop ax.25 route records in cases where routes
  7.  * were added by the connections. Inspired by K4TQL
  8.  */
  9. #include "lapb.h"
  10. #ifdef AX25
  11. #include "netrom.h"
  12.  
  13. #if !defined(_lint)
  14. static char rcsid[] OPTIONAL = "$Id: lapb.c,v 1.17 1997/09/14 14:37:46 root Exp root $";
  15. #endif
  16.  
  17. /* This forces data sent by jumpstarting a mailbox connect to
  18.  * resend the header etc. when the first UA reply is missed, and
  19.  * a second SABM is received for the same connection
  20.  * added by Ron Murray VK6ZJM, Murray_RJ@cc.curtin.edu.au
  21.  */
  22. #define SABM_HOLDOFF
  23.  
  24. static void handleit (struct ax25_cb * axp, int pid, struct mbuf * bp);
  25. static void procdata (struct ax25_cb * axp, struct mbuf * bp);
  26. static int ackours (struct ax25_cb * axp, int16 n);
  27. static void clr_ex (struct ax25_cb * axp);
  28. static void enq_resp (struct ax25_cb * axp);
  29. static void inv_rex (struct ax25_cb * axp);
  30. static void drop_axr (struct ax25_cb * axp);
  31.  
  32. /*needed for mailbox jumpstart - WG7J */
  33. #ifdef MAILBOX
  34. #ifdef NETROM
  35. extern struct nrnbr_tab *find_nrnbr (char *, struct iface *);
  36. #endif
  37.  
  38. extern int Mbjumpstart;
  39. extern struct no_js *Exclude;
  40. #endif
  41.  
  42.  
  43. /*If we have an AX.25 AUTO route record, drop it.*/
  44. static void
  45. drop_axr (struct ax25_cb *axp)
  46. {
  47. struct ax_route *axr;
  48.  
  49.     axr = ax_lookup (NULLCHAR, axp->remote, axp->iface, AX_NONSETUP);
  50.     if (axr != NULLAXR && axr->type != AX_LOCAL)
  51.         (void) ax_drop (axp->remote, axp->iface, AX_NONSETUP);
  52. }
  53.  
  54.  
  55.  
  56. /* Process incoming frames */
  57. int
  58. lapb_input (axp, cmdrsp, bp)
  59. struct ax25_cb *axp;        /* Link control structure */
  60. int cmdrsp;            /* Command/response flag */
  61. struct mbuf *bp;        /* Rest of frame, starting with ctl */
  62. {
  63. int control;
  64. int class;        /* General class (I/S/U) of frame */
  65. int16 type;        /* Specific type (I/RR/RNR/etc) of frame */
  66. char pf;        /* extracted poll/final bit */
  67. char poll = 0;
  68. char final = 0;
  69. int16 nr;        /* ACK number of incoming frame */
  70. int16 ns = 0;        /* Seq number of incoming frame */
  71. int16 tmp;
  72. int recovery = 0;
  73. #ifdef MAILBOX
  74. struct no_js *ep;    /*scan the 'exclude-calls' list */
  75. #endif
  76.  
  77.     if (bp == NULLBUF || axp == NULLAX25 || axp->iface == NULLIF) {
  78.         free_p (bp);
  79.         return -1;
  80.     }
  81.     /* Extract the various parts of the control field for easy use */
  82.     if ((control = PULLCHAR (&bp)) == -1) {        /*lint !e506 */
  83.         free_p (bp);    /* Probably not necessary */
  84.         return -1;
  85.     }
  86.  
  87.     /* update the counters for messages in */
  88.     axp->iface->axcnt.msgin++;
  89.  
  90.     type = ftype (control);
  91.     class = type & 0x3;
  92.     pf = control & PF;
  93.     /* Check for polls and finals */
  94.     if (pf) {
  95.         switch (cmdrsp) {
  96.             case LAPB_COMMAND:
  97.                 poll = YES;
  98.                 break;
  99.             case LAPB_RESPONSE:
  100.                 final = YES;
  101.                 break;
  102.             default:
  103.                 break;
  104.         }
  105.     }
  106.     /* Extract sequence numbers, if present */
  107.     switch (class) {
  108.         case I:
  109.         case I + 2:
  110.             ns = (control >> 1) & MMASK;    /*lint !e702 !e616 */
  111.         case S:    /* Note fall-thru */
  112.         default:
  113.             nr = (control >> 5) & MMASK;    /*lint !e702 */
  114.             break;
  115.     }
  116.     /* This section follows the SDL diagrams by K3NA fairly closely */
  117.     switch (axp->state) {
  118.         case LAPB_DISCONNECTED:
  119.             switch (type) {
  120.                 case SABM:    /* Initialize or reset link */
  121.                     /* This a new incoming connection. */
  122.                     (void) sendctl (axp, LAPB_RESPONSE, UA | pf);    /* Always accept */
  123.                     clr_ex (axp);
  124.                     axp->unack = axp->vr = axp->vs = 0;
  125.                     lapbstate (axp, LAPB_CONNECTED);    /* Resets state counters */
  126.                     axp->srt = axp->iface->ax25->irtt;
  127.                     axp->mdev = 0;
  128.                     set_timer (&axp->t1, 2 * axp->srt);
  129.                     start_timer (&axp->t3);
  130.                     start_timer (&axp->t4);
  131. #ifdef SABM_HOLDOFF
  132.                     axp->flags.rxd_I_frame = 0;    /* nothing received yet */
  133. #endif
  134.                     /*Jump-start the mailbox. This causes the [NET-H$] prompt to
  135.                      *be sent Immediately, instead of after the first data packet
  136.                      *Check for connections from known netrom calls,
  137.                      *calls from the 'jumpstart exclude' list and check if interface
  138.                      *is in vc mode...
  139.                      *we don't want to start the mailbox in these cases,
  140.                      *since these could be attempts to do level 3 stuff.
  141.                      *12/09/91 WG7J
  142.                      */
  143. #ifdef MAILBOX
  144.                     if (axp->jumpstarted & IP_LINK)
  145.                         break;
  146.                     if (Mbjumpstart) {
  147. #ifdef NETROM
  148.                         if (axp->jumpstarted == NETROM_LINK) {
  149.                             /* check if the incoming interface is enabled for netrom*/
  150.                             if (axp->iface->flags & IS_NR_IFACE)
  151.                                 if (find_nrnbr (axp->remote, axp->iface) != NULLNTAB)
  152.                                     /* this is a netrom neighbour*/
  153.                                     break;
  154.                         }
  155. #endif /* NETROM */
  156.                         /*Now check the 'exclude' list*/
  157.                         for (ep = Exclude; ep != (struct no_js *) NULL; ep = ep->next)
  158.                             if (addreq (axp->remote, ep->call))
  159.                                 break;
  160.                         if (ep != (struct no_js *) NULL)    /*exclude this one*/
  161.                             break;
  162.  
  163.                         /*We passed all tests!*/
  164.                         axp->jumpstarted += JUMPSTARTED;
  165.                         s_arcall (axp, 0);
  166.                     }
  167. #endif /* MAILBOX */
  168.                     break;
  169.                 case DISC:    /* Always answer a DISC with a DM */
  170.                     (void) sendctl (axp, LAPB_RESPONSE, DM | pf);
  171.                     break;
  172.                 case DM:    /* Ignore to avoid infinite loops */
  173.                     break;
  174.                 default:    /* All others get DM */
  175.                     if (poll)
  176.                         (void) sendctl (axp, LAPB_RESPONSE, DM | pf);
  177.                     break;
  178.             }
  179.             if (axp->state == LAPB_DISCONNECTED) {    /* we can close connection */
  180. #if 0
  181.                 stop_timer (&axp->t1);    /* waste all the timers */
  182.                 stop_timer (&axp->t3);
  183.                 stop_timer (&axp->t4);
  184.                 free_q (&axp->txq);    /* lose transmit queue */
  185. #endif
  186.                 drop_axr (axp);    /* drop ax25 route */
  187.                 del_ax25 (axp);    /* clean out the trash */
  188.                 free_p (bp);
  189.                 return 0;
  190.             }
  191.             break;
  192.         case LAPB_SETUP:
  193.             switch (type) {
  194.                 case SABM:    /* Simultaneous open */
  195.                     (void) sendctl (axp, LAPB_RESPONSE, UA | pf);
  196.                     break;
  197.                 case DISC:
  198.                     (void) sendctl (axp, LAPB_RESPONSE, DM | pf);
  199. #ifdef NETROM
  200.                     nr_derate (axp);
  201. #endif
  202.                     drop_axr (axp);    /* drop ax25 route */
  203.                     free_q (&axp->txq);
  204.                     stop_timer (&axp->t1);
  205.                     axp->reason = LB_DM;
  206.                     lapbstate (axp, LAPB_DISCONNECTED);
  207.                     free_p (bp);
  208.                     return 0;
  209.  
  210.                 case UA:    /* Connection accepted */
  211.                     /* Note: xmit queue not cleared */
  212.                     stop_timer (&axp->t1);
  213.                     start_timer (&axp->t3);
  214.                     axp->unack = axp->vr = axp->vs = 0;
  215.                     lapbstate (axp, LAPB_CONNECTED);
  216.                     start_timer (&axp->t4);
  217.                     break;
  218.                 case DM:    /* Connection refused */
  219.                     free_q (&axp->txq);
  220.                     stop_timer (&axp->t1);
  221.                     axp->reason = LB_DM;
  222.                     lapbstate (axp, LAPB_DISCONNECTED);
  223.                     free_p (bp);
  224.                     return 0;
  225.  
  226.                 default:    /* Respond with DM only to command polls */
  227.                     if (poll)
  228.                         (void) sendctl (axp, LAPB_RESPONSE, DM | pf);
  229.                     break;
  230.             }
  231.             break;
  232.         case LAPB_DISCPENDING:
  233.             switch (type) {
  234.                 case SABM:
  235.                     (void) sendctl (axp, LAPB_RESPONSE, DM | pf);
  236.                     drop_axr (axp);    /* drop ax25 route */
  237.                     break;
  238.                 case DISC:
  239.                     (void) sendctl (axp, LAPB_RESPONSE, UA | pf);
  240.                     drop_axr (axp);    /* drop ax25 route */
  241.                     break;
  242.                 case UA:
  243.                 case DM:
  244.                     stop_timer (&axp->t1);
  245.                     lapbstate (axp, LAPB_DISCONNECTED);
  246.                     free_p (bp);
  247.                     return 0;
  248.  
  249.                 default:    /* Respond with DM only to command polls */
  250.                     if (poll)
  251.                         (void) sendctl (axp, LAPB_RESPONSE, DM | pf);
  252.                     drop_axr (axp);    /* drop ax25 route */
  253.                     break;
  254.             }
  255.             break;
  256.         case LAPB_RECOVERY:    /* folded these two cases together */
  257.             recovery = 1;    /* fall through */
  258.         case LAPB_CONNECTED:
  259.             switch (type) {
  260.                 case SABM:
  261.                     (void) sendctl (axp, LAPB_RESPONSE, UA | pf);
  262. #ifdef SABM_HOLDOFF
  263.                     if (axp->flags.rxd_I_frame) {
  264.                         /* only reset if we've had a */
  265.                         /* valid I-frame. Otherwise he */
  266.                         /* may just not have got our UA */
  267. #endif
  268.                         clr_ex (axp);
  269.                         if (!recovery)
  270.                             free_q (&axp->txq);
  271.                         stop_timer (&axp->t1);
  272.                         start_timer (&axp->t3);
  273.                         axp->unack = axp->vr = axp->vs = 0;
  274.                         lapbstate (axp, LAPB_CONNECTED);    /* Purge queues */
  275.                         if (recovery && !run_timer (&axp->t4))
  276.                             start_timer (&axp->t4);
  277. #ifdef SABM_HOLDOFF
  278.                     }
  279. #endif
  280.                     break;
  281.                 case DISC:
  282.                     free_q (&axp->txq);
  283.                     (void) sendctl (axp, LAPB_RESPONSE, UA | pf);
  284.                     stop_timer (&axp->t1);
  285.                     stop_timer (&axp->t3);
  286.                     axp->reason = LB_NORMAL;
  287.                     lapbstate (axp, LAPB_DISCONNECTED);
  288.                     free_p (bp);
  289.                     return 0;
  290.  
  291.                 case DM:
  292. #ifdef NETROM
  293.                     if (recovery)
  294.                         nr_derate (axp);
  295. #endif
  296.                     axp->reason = LB_DM;
  297.                     lapbstate (axp, LAPB_DISCONNECTED);
  298.                     free_p (bp);
  299.                     return 0;
  300.  
  301.                 case UA:
  302.                     est_link (axp);
  303.                     lapbstate (axp, LAPB_SETUP);    /* Re-establish */
  304.                     break;
  305.                 case FRMR:
  306.                     /* update the counters for FRMR in */
  307.                     if (axp && axp->iface)
  308.                         axp->iface->axcnt.frmerr++;
  309.                         
  310.                     est_link (axp);
  311.                     lapbstate (axp, LAPB_SETUP);    /* Re-establish link */
  312.                     break;
  313.                 case RR:
  314.                 case RNR:
  315.                     axp->flags.remotebusy = (type == RNR) ? YES : NO;
  316.  
  317.                     if (type == RNR)
  318.                         /* update the counters for RNR in */
  319.                         axp->iface->axcnt.rnrin++;
  320.  
  321.                     if (recovery && (axp->proto == V1 || final)) {
  322.                         stop_timer (&axp->t1);
  323.                         (void) ackours (axp, nr);
  324.                         if (axp->unack != 0) {
  325.                             if (control != RNR || axp->pthresh != 65535)
  326.                                 inv_rex (axp);
  327.                             else {
  328.                                 stop_timer (&axp->t1);
  329.                                 start_timer (&axp->t3);
  330.                             }
  331.                         } else {
  332.                             start_timer (&axp->t3);
  333.                             lapbstate (axp, LAPB_CONNECTED);
  334.                             if (!run_timer (&axp->t4))
  335.                                 start_timer (&axp->t4);
  336.                         }
  337.                     } else {
  338.                         if (poll)
  339.                             enq_resp (axp);
  340.                         (void) ackours (axp, nr);
  341.                         /* Keep timer running even if all frames
  342.                          * were acked, since we must see a Final
  343.                          */
  344. #if 1
  345.                         if ((type == RNR) && axp->pthresh == 65535) {
  346.                             stop_timer (&axp->t1);
  347.                             start_timer (&axp->t3);
  348.                         } else if (recovery) {
  349. #endif
  350.                             if (!run_timer (&axp->t1))
  351.                                 start_timer (&axp->t1);
  352.                         }
  353.                     }
  354.                     break;
  355.                 case REJ:
  356.                     axp->flags.remotebusy = NO;
  357.  
  358.                     /* update the counters for rej in */
  359.                     axp->iface->axcnt.rejin++;
  360.  
  361.                     if (recovery) {
  362.                         /* Don't insist on a Final response from the old proto */
  363.                         if (axp->proto == V1 || final) {
  364.                             stop_timer (&axp->t1);
  365.                             (void) ackours (axp, nr);
  366.                             if (axp->unack != 0) {
  367.                                 inv_rex (axp);
  368.                             } else {
  369.                                 start_timer (&axp->t3);
  370.                                 lapbstate (axp, LAPB_CONNECTED);
  371.                                 if (!run_timer (&axp->t4))
  372.                                     start_timer (&axp->t4);
  373.                             }
  374.                         } else {
  375.                             if (poll)
  376.                                 enq_resp (axp);
  377.                             (void) ackours (axp, nr);
  378.                             if (axp->unack != 0) {
  379.                                 /* This is certain to trigger output */
  380.                                 inv_rex (axp);
  381.                             }
  382.                             /* A REJ that acks everything but doesn't
  383.                              * have the F bit set can cause a deadlock.
  384.                              * So make sure the timer is running.
  385.                              */
  386.                             if (!run_timer (&axp->t1))
  387.                                 start_timer (&axp->t1);
  388.                         }
  389.                     } else {
  390.                         if (poll)
  391.                             enq_resp (axp);
  392.                         (void) ackours (axp, nr);
  393.                         stop_timer (&axp->t1);
  394.                         start_timer (&axp->t3);
  395.                         /* This may or may not actually invoke transmission,
  396.                          * depending on whether this REJ was caused by
  397.                          * our losing his prior ACK.
  398.                          */
  399.                         inv_rex (axp);
  400.                     }
  401.                     break;
  402.                 case I:
  403.                     (void) ackours (axp, nr);    /** == -1) */
  404.  
  405.                     /* update the counters for data in */
  406.                     axp->iface->axcnt.datain++;
  407. #ifdef SABM_HOLDOFF
  408.                     axp->flags.rxd_I_frame = 1;    /* we got something */
  409. #endif
  410.                     if (recovery) {
  411.                         /* Make sure timer is running, since an I frame
  412.                          * cannot satisfy a poll
  413.                          */
  414.                         if (!run_timer (&axp->t1))
  415.                             start_timer (&axp->t1);
  416.                     } else
  417.                         start_timer (&axp->t4);
  418.                     if (len_p (axp->rxq) >= axp->window) {
  419.                         /* Too bad he didn't listen to us; he'll
  420.                          * have to resend the frame later. This
  421.                          * drastic action is necessary to avoid
  422.                          * deadlock.
  423.                          */
  424.                         if (recovery || poll)    {
  425.                             (void) sendctl (axp, LAPB_RESPONSE, RNR | pf);
  426.                             
  427.                             /* update the counters for rnr out */
  428.                             axp->iface->axcnt.rnrout++;
  429.                         }
  430.                         free_p (bp);
  431.                         bp = NULLBUF;
  432.                         break;
  433.                     }
  434.                     /* Reject or ignore I-frames with receive sequence number errors */
  435.                     if ((char) ns != axp->vr) {
  436.                         if (axp->proto == V1 || !axp->flags.rejsent) {
  437.                             axp->flags.rejsent = YES;
  438.                             (void) sendctl (axp, LAPB_RESPONSE, REJ | pf);
  439.  
  440.                             /* update the counters for rej out */
  441.                             axp->iface->axcnt.rejout++;
  442.                         } else if (poll)
  443.                             enq_resp (axp);
  444.                         axp->response = 0;
  445.                         break;
  446.                     }
  447.                     axp->flags.rejsent = NO;
  448.                     axp->vr = (axp->vr + 1) & MMASK;
  449.                     tmp = len_p (axp->rxq) >= axp->window ? RNR : RR;
  450.                     if (poll)    {
  451.                         (void) sendctl (axp, LAPB_RESPONSE, tmp | PF);
  452.  
  453.                         if (tmp == RNR)
  454.                             /* update the counters for rnr out */
  455.                             axp->iface->axcnt.rnrout++;
  456.                     } else
  457.                         axp->response = (char) tmp;
  458.  
  459.                     procdata (axp, bp);
  460.                     bp = NULLBUF;
  461.                     break;
  462.                 default:    /* All others ignored */
  463.                     break;
  464.             }
  465.             break;
  466.         default:
  467.             break;
  468.     }
  469.     free_p (bp);        /* In case anything's left */
  470.  
  471.     /* See if we can send some data, perhaps piggybacking an ack.
  472.      * If successful, lapb_output will clear axp->response.
  473.      */
  474.     (void) lapb_output (axp);
  475.  
  476.     if (axp && axp->response != 0) {
  477.         (void) sendctl (axp, LAPB_RESPONSE, axp->response);
  478.  
  479.         if (axp->response == RNR)
  480.             /* update the counters for rnr out */
  481.             axp->iface->axcnt.rnrout++;
  482.  
  483.         axp->response = 0;
  484.     }
  485.     return 0;
  486. }
  487.  
  488.  
  489.  
  490. /* Handle incoming acknowledgements for frames we've sent.
  491.  * Free frames being acknowledged.
  492.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  493.  */
  494. static int
  495. ackours (struct ax25_cb *axp, int16 n)
  496. {
  497. struct mbuf *bp;
  498. int acked = 0;        /* Count of frames acked by this ACK */
  499. int16 oldest;        /* Seq number of oldest unacked I-frame */
  500. int32 rtt, abserr;
  501.  
  502.     /* Free up acknowledged frames by purging frames from the I-frame
  503.      * transmit queue. Start at the remote end's last reported V(r)
  504.      * and keep going until we reach the new sequence number.
  505.      * If we try to free a null pointer,
  506.      * then we have a frame reject condition.
  507.      */
  508.     oldest = (axp->vs - axp->unack) & MMASK;
  509.     while (axp->unack != 0 && oldest != n) {
  510.         if ((bp = dequeue (&axp->txq)) == NULLBUF) {
  511.             /* Acking unsent frame */
  512.             return -1;
  513.         }
  514.         free_p (bp);
  515.         axp->unack--;
  516.         acked++;
  517.         if (axp->flags.rtt_run && axp->rtt_seq == oldest) {
  518.             /* A frame being timed has been acked */
  519.             axp->flags.rtt_run = 0;
  520.             /* Update only if frame wasn't retransmitted */
  521.             if (!axp->flags.retrans) {
  522.                 rtt = msclock () - axp->rtt_time;
  523.                 abserr = (rtt > axp->srt) ? rtt - axp->srt :
  524.                     axp->srt - rtt;
  525.  
  526.                 /* Run SRT and mdev integrators */
  527.                 axp->srt = ((axp->srt * 7) + rtt + 4) >> 3;        /*lint !e704 */
  528.                 axp->mdev = ((axp->mdev * 3) + abserr + 2) >> 2;    /*lint !e704 */
  529.                 /* Update timeout */
  530.                 set_timer (&axp->t1, 4 * axp->mdev + axp->srt);
  531.             }
  532.         }
  533.         axp->flags.retrans = 0;
  534.         axp->retries = 0;
  535.         oldest = (oldest + 1) & MMASK;
  536.     }
  537.     if (axp->unack == 0) {
  538.         /* All frames acked, stop timeout */
  539.         stop_timer (&axp->t1);
  540.         start_timer (&axp->t3);
  541.     } else if (acked != 0)         /* Partial ACK; restart timer */
  542.         start_timer (&axp->t1);
  543.  
  544.     if (acked != 0) {
  545.         /* If user has set a transmit upcall, indicate how many frames
  546.          * may be queued
  547.          */
  548.         if (axp->t_upcall != NULLVFP ((struct ax25_cb *, int)))
  549.             (*axp->t_upcall) (axp, axp->paclen * (axp->maxframe - axp->unack));
  550.     }
  551.     return 0;
  552. }
  553.  
  554.  
  555.  
  556. /* Establish data link */
  557. void
  558. est_link (struct ax25_cb *axp)
  559. {
  560.     clr_ex (axp);
  561.     axp->retries = 0;
  562.     (void) sendctl (axp, LAPB_COMMAND, SABM | PF);
  563.     stop_timer (&axp->t3);
  564.     start_timer (&axp->t1);
  565. }
  566.  
  567.  
  568.  
  569. /* Clear exception conditions */
  570. static void
  571. clr_ex (struct ax25_cb *axp)
  572. {
  573.     axp->flags.remotebusy = NO;
  574.     axp->flags.rejsent = NO;
  575.     axp->response = 0;
  576.     stop_timer (&axp->t3);
  577. }
  578.  
  579.  
  580.  
  581. /* Enquiry response */
  582. static void
  583. enq_resp (struct ax25_cb *axp)
  584. {
  585. char ctl;
  586.  
  587.     ctl = len_p (axp->rxq) >= axp->window ? RNR | PF : RR | PF;
  588.     (void) sendctl (axp, LAPB_RESPONSE, ctl);
  589.  
  590.     if (ctl == (RNR | PF))
  591.         /* update the counters for rnr out */
  592.         axp->iface->axcnt.rnrout++;
  593.  
  594.     axp->response = 0;
  595.     stop_timer (&axp->t3);
  596. }
  597.  
  598.  
  599.  
  600. /* Invoke retransmission */
  601. static void
  602. inv_rex (struct ax25_cb *axp)
  603. {
  604.     axp->vs -= axp->unack;
  605.     axp->vs &= MMASK;
  606.     axp->unack = 0;
  607. }
  608.  
  609.  
  610.  
  611. /* Send S or U frame to currently connected station */
  612. int
  613. sendctl (struct ax25_cb *axp, int cmdrsp, int cmd)
  614. {
  615.     if ((ftype ((char) cmd) & 0x3) == S)    /* Insert V(R) if S frame */
  616.         cmd |= (axp->vr << 5);        /*lint !e701 */
  617.  
  618.     return sendframe (axp, cmdrsp, cmd, NULLBUF);
  619. }
  620.  
  621.  
  622.  
  623. /* Start data transmission on link, if possible
  624.  * Return number of frames sent
  625.  */
  626. int
  627. lapb_output (register struct ax25_cb *axp)
  628. {
  629. register struct mbuf *bp;
  630. struct mbuf *tbp;
  631. char control;
  632. int sent = 0;
  633. int i;
  634.  
  635.     if (axp == NULLAX25 || axp->iface == NULLIF
  636.         || (axp->state != LAPB_RECOVERY && axp->state != LAPB_CONNECTED)
  637.         || axp->flags.remotebusy)
  638.         return 0;
  639.  
  640.     /* Dig into the send queue for the first unsent frame */
  641.     bp = axp->txq;
  642.     for (i = 0; i < axp->unack; i++) {
  643.         if (bp == NULLBUF)
  644.             break;    /* Nothing to do */
  645.         bp = bp->anext;
  646.     }
  647.     /* Start at first unsent I-frame, stop when either the
  648.      * number of unacknowledged frames reaches the maxframe limit,
  649.      * or when there are no more frames to send
  650.      */
  651.     while (bp != NULLBUF && axp->unack < axp->maxframe) {
  652.         control = (char) (I | (axp->vs++ << 1) | (axp->vr << 5));    /*lint !e701 */
  653.         axp->vs &= MMASK;
  654.         (void) dup_p (&tbp, bp, 0, len_p (bp));
  655.         if (tbp == NULLBUF)
  656.             return sent;    /* Probably out of memory */
  657.         (void) sendframe (axp, LAPB_COMMAND, control, tbp);
  658.         start_timer (&axp->t4);
  659.         axp->unack++;
  660.         /* We're implicitly acking any data he's sent, so stop any
  661.          * delayed ack
  662.          */
  663.         axp->response = 0;
  664.         if (!run_timer (&axp->t1)) {
  665.             stop_timer (&axp->t3);
  666.             start_timer (&axp->t1);
  667.         }
  668.         sent++;
  669.  
  670.         /* update the counters for data out */
  671.         axp->iface->axcnt.dataout++;
  672.  
  673.         bp = bp->anext;
  674.         if (!axp->flags.rtt_run) {
  675.             /* Start round trip timer */
  676.             axp->rtt_seq = (control >> 1) & MMASK;        /*lint !e702 */
  677.             axp->rtt_time = msclock ();
  678.             axp->flags.rtt_run = 1;
  679.         }
  680.     }
  681.     return sent;
  682. }
  683.  
  684.  
  685.  
  686. /* Set new link state */
  687. void
  688. lapbstate (struct ax25_cb *axp, int s)
  689. {
  690. int oldstate;
  691.  
  692.     oldstate = axp->state;
  693.     axp->state = s;
  694.     if (s == LAPB_DISCONNECTED) {
  695.         stop_timer (&axp->t1);
  696.         stop_timer (&axp->t3);
  697.         stop_timer (&axp->t4);
  698.         free_q (&axp->txq);
  699.         drop_axr (axp);    /* any ax25 route that hasn't been dropped yet*/
  700.     }
  701.     /* Don't bother the client unless the state is really changing */
  702.     if ((oldstate != s) && (axp->s_upcall != NULLVFP ((struct ax25_cb *, int, int))))
  703.         (*axp->s_upcall) (axp, oldstate, s);
  704. }
  705.  
  706.  
  707.  
  708. /* Process a valid incoming I frame */
  709. static void
  710. procdata (struct ax25_cb *axp, struct mbuf *bp)
  711. {
  712. int pid;
  713. int seq;
  714.  
  715.     /* Extract level 3 PID */
  716.     if ((pid = PULLCHAR (&bp)) == -1)        /*lint !e506 */
  717.         return;        /* No PID */
  718.  
  719.     if (axp->segremain != 0) {
  720.         /* Reassembly in progress; continue */
  721.         seq = PULLCHAR (&bp);            /*lint !e506 */
  722.         if (pid == PID_SEGMENT && (seq & SEG_REM) == axp->segremain - 1) {
  723.             /* Correct, in-order segment */
  724.             append (&axp->rxasm, bp);
  725.  
  726.             /* update the counters for segments in */
  727.             axp->iface->axcnt.segin++;
  728.  
  729.             if ((axp->segremain = (seq & SEG_REM)) == 0) {
  730.  
  731.                 /* update the counters for segment errors */
  732.                 axp->iface->axcnt.segerr++;
  733.  
  734.                 /* Done; kick it upstairs */
  735.                 bp = axp->rxasm;
  736.                 axp->rxasm = NULLBUF;
  737.                 pid = PULLCHAR (&bp);    /*lint !e506 */
  738.                 handleit (axp, pid, bp);
  739.             }
  740.         } else {
  741.             /* Error! */
  742.             free_p (axp->rxasm);
  743.             axp->rxasm = NULLBUF;
  744.             axp->segremain = 0;
  745.             free_p (bp);
  746.         }
  747.     } else {
  748.         /* No reassembly in progress */
  749.         if (pid == PID_SEGMENT) {
  750.             /* update the counters for segments in */
  751.             axp->iface->axcnt.segin++;
  752.  
  753.             /* Start reassembly */
  754.             seq = PULLCHAR (&bp);        /*lint !e506 */
  755.             if (!(seq & SEG_FIRST))
  756.                 free_p (bp);    /* not first seg - error! */
  757.             else {
  758.                 /* Put first segment on list */
  759.                 axp->segremain = seq & SEG_REM;
  760.                 axp->rxasm = bp;
  761.             }
  762.         } else         /* Normal frame; send upstairs */
  763.             handleit (axp, pid, bp);
  764.     }
  765. }
  766.  
  767.  
  768.  
  769. /* New-style frame segmenter. Returns queue of segmented fragments, or
  770.  * original packet if small enough
  771.  */
  772. struct mbuf *
  773. segmenter (bp, ssize, axp)
  774. struct mbuf *bp;        /* Complete packet */
  775. int16 ssize;            /* Max size of frame segments */
  776. struct ax25_cb *axp;
  777. {
  778. struct mbuf *result = NULLBUF;
  779. struct mbuf *bptmp, *bp1;
  780. int16 len, offset;
  781. int segments;
  782.  
  783.     /* See if packet is too small to segment. Note 1-byte grace factor
  784.      * so the PID will not cause segmentation of a 256-byte IP datagram.
  785.      */
  786.     len = len_p (bp);
  787.     if (len <= ssize + 1)
  788.         return bp;    /* Too small to segment */
  789.  
  790.     ssize -= 2;        /* ssize now equal to data portion size */
  791.     segments = 1 + (len - 1) / ssize;    /* # segments  */
  792.     offset = 0;
  793.  
  794.     /* update the counters for seqments out */
  795.     if (axp && axp->iface)
  796.         axp->iface->axcnt.segout += segments;
  797.  
  798.     while (segments != 0) {
  799.         offset += dup_p (&bptmp, bp, offset, ssize);
  800.         if (bptmp == NULLBUF) {
  801.             free_q (&result);
  802.             break;
  803.         }
  804.         /* Make room for segmentation header */
  805.         if ((bp1 = pushdown (bptmp, 2)) == NULLBUF) {
  806.             free_p (bptmp);
  807.             free_q (&result);
  808.             break;
  809.         }
  810.         bp1->data[0] = PID_SEGMENT;
  811.         bp1->data[1] = uchar(--segments);
  812.         if (offset == ssize)
  813.             bp1->data[1] |= SEG_FIRST;
  814.         enqueue (&result, bp1);
  815.     }
  816.     free_p (bp);
  817.     return result;
  818. }
  819.  
  820.  
  821.  
  822. static void
  823. handleit (struct ax25_cb *axp, int pid, struct mbuf *bp)
  824. {
  825. struct axlink *ipp;
  826.  
  827.     for (ipp = Axlink; ipp->funct != NULL; ipp++) {
  828.         if (ipp->pid == pid)
  829.             break;
  830.     }
  831.     if (ipp->funct != NULL)
  832.         (*ipp->funct) (axp->iface, axp, NULLCHAR, NULLCHAR, bp, 0);
  833.     else
  834.         free_p (bp);
  835. }
  836.  
  837.  
  838.  
  839. #endif /* AX25 */
  840.